Visual Basicプログラム作成手順 (API関数使用の例)


これから、Visual Basicを使ってパソコン−PIC間のデータ通信プログラムを作成していきます。目的としては、パソコンからPICへのデータ通信により、PICのポートを介して接続されている周辺回路を制御します。また逆に、PICからパソコンへのデータ通信により、A/D変換したPIC内のデータをパソコンに取り込んだりします。なお、取り込んだデータは、表示/解析/保存といったデータ処理を行い、スペアナだけではなく汎用的に応用できるプログラムを作成していきます。お楽しみに!

<項目>Visual Basicの起動
Visual Basicをインストールして初めて起動すると、図1のような「新しいプロジェクト」というダイアログが表示されます。

Visual Basic起動時の画面
図1.Visual Basic起動時の画面
    (Ver.5.0 Professional Edition)

Visual Basicでプログラムを作成する場合、まず図1の画面でこれから作成するプロジェクト(プログラム)の種類を選択する必要があります。上から、標準EXE,ActiveX EXE,ActiveX DLL,ActiveXコントロール,アプリケーションウィザード,VB Professional...,アドイン,ActiveXドキュメントDLL,ActiveXドキュメントEXE という項目が表示されました(Ver.5.0 Professional Editionの場合)。ここでは、単独で実行可能なEXE形式のプログラムで、Windows上で動作する最も基本的なプログラムを作成しますので、「標準EXE」を選択します。選択すると、「標準コントロール」のみがツールボックスに表示されます。

Visual Basicの画面
図2.Visual Basicの画面

図2に、Visual Basicの画面例を示します。画面の細かな説明については、Visual Basicに関する多数の入門書に書かれていますので、そちらをご覧いただきたいと思います。今回は、Windows API(Application Programming Interface)関数を利用したプログラム作成に主点を置いて解説していきましょう。


<項目>標準モジュールの追加
一般にAPI関数は、標準モジュール内の宣言領域(GeneralのDeclarations)に記述します。フォームモジュール内の宣言領域にも記述可能ですが、ただし「Declare」の前に「Private」を付けないと、他のモジュールから利用できません。APIビューアを使ってAPI関数の記述をそのままコピーして宣言領域に貼り付けた方が簡単ですので、ここは標準モジュールを追加します。
Visual Basic画面右の「プロジェクト1−Project1」のウインドウ(プロジェクトエクスプローラ)内に「Form1(Form1)」というのがあります。ここを右クリックし、「追加()」→「標準モジュール()」を選択すると、図3の標準モジュールの追加ダイアログが表示されます。もしくは、画面上のメニューにある「プロジェクト()」から「標準モジュールの追加()」から、標準モジュールの追加ダイアログを表示させます。ここで標準モジュールを追加する場合には、「開く()」をクリックします。図4のプロジェクトエクスプローラに示すように「Module1」という標準モジュールが追加されました。

標準モジュールの追加ダイアログ
図3.標準モジュールの追加ダイアログ
標準モジュールが追加されたことを示すプロジェクトエクスプローラ
図4.標準モジュールが追加された
ことを示すプロジェクトエクスプローラ


<項目>API関数の記述(標準モジュール)
基本的には、APIビューアから使用したい関数をコピーし、標準モジュールの宣言領域(General のDeclarations)のコードウインドウ内に貼り付けていきます。APIビューアの使い方やAPI関数の詳細については、前ページをご覧ください。使用したAPI関数を下記に示します。なお、パラメータには構造体を含む所がありますが、簡単のため「Long」型に変更して利用する場合もあります。CreateFile関数の4番目のパラメータ「lpSecurityAttributes」のところですが、APIビューアで取得したままでは、構造体を含む形になっているため、「As Long」に変更し、「ByVal」をつけて値渡しとしてください。WriteFile関数及びReadFile関数の5番目のパラメータ「lpOverlapped」のところですが、APIビューアで取得したままでは、構造体を含む形になっているため、「As Long」に変更してください。なお、「」がついた所は、コメントとして扱われます。また、ホームページ表示の都合上、Declare文が複数行に折り返されていますが、コードウインドウでは1行で記述します。


'シリアルポートのオープン関数の定義
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

'シリアルポートのクローズ関数の定義
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

'シリアルポートの設定関数の定義
Declare Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As Long

'タイムアウトの設定関数の定義
Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long

'データの送信関数の定義
Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Long) As Long

'データの受信関数の定義
Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long

なお、API関数で使われている構造体の定義についても、標準モジュールの宣言領域(General のDeclarations)のコードウインドウ内に貼り付けていきます。ここでは、シリアルポートの設定関数であるSetCommState関数の2番目のパラメータに、DCB構造体と、タイムアウトの設定関数であるSetCommTimeouts関数の2番目のパラメータに、COMMTIMEOUTS構造体があります。

' DCB構造体の定義
Type DCB
    DCBlength As Long
    BaudRate As Long
    fBitFields As Long
    wReserved As Integer
    XonLim As Integer
    XoffLim As Integer
    ByteSize As Byte
    Parity As Byte
    StopBits As Byte
    XonChar As Byte
    XoffChar As Byte
    ErrorChar As Byte
    EofChar As Byte
    EvtChar As Byte
End Type

' COMMTIMEOUTS構造体の定義
Type COMMTIMEOUTS
    ReadIntervalTimeout As Long
    ReadTotalTimeoutMultiplier As Long   
    ReadTotalTimeoutConstant As Long   
    WriteTotalTimeoutMultiplier As Long   
    WriteTotalTimeoutConstant As Long   
End Type



'構造体のサイズ
'ボーレイト(bps)の設定
'ビット単位のフィールド定義
'予約(0をセットする)
'受信バッファ中のデータが何バイトになったらXon文字を送るかを指定
'受信バッファの空きが何バイトになったらXoff文字を送るかを指定
'1データのビット数を指定
'パリティの方式を指定
'ストップビット数を指定
'Xon文字を指定
'Xoff文字を指定
'パリティエラーの場合に使う文字を指定
'非バイナリモードの場合のデータ終了文字の指定
'イベントを生成する文字を指定





'文字の読み込みの待ち時間
'読み込みの1文字あたりの時間
'読み込みの定数時間
'書き込みの1文字あたりの時間
'書き込みの定数時間




<項目>画面のデザイン(フォームウインドウ)
Visual Basicで作成するプログラムは、実行時にウインドウを表示させますので、次に画面のデザインを行います。図5に示すようなフォームウインドウを使って、プログラムの実行時に表示させたいものを配置していきます。まず簡単のため、シリアル通信の送信データを入力するコントロールと、PIC側からの受信データを表示するコントロールを配置します。ここでは図5に示すように、テキストボックスの「Text1」と「Text2」を使いました。また、そのコントロールの役割を識別できるように、テキスト表示として「Label1」と「Label2」も配置しました。なお、簡単なプログラムのタイトル表示として、「Label3」を配置しました。シリアル通信の開始には、コマンドボタンとして、「Command1」を配置しました。

Visual Basicのフォームウインドウ
図5.Visual Basicのフォームウインドウ



<項目>プログラムの記述(フォームモジュール)
Visual Basicでは、フォームを土台にしてプログラムを作っていきますが、その中身は全てフォームモジュールに記述されます。すなわち、フォーム上に配置したコントロールやそのプロパティ、イベントプロシージャ、変数、定数などは、全てフォームモジュールにソースコードとして記述していくわけです。

Private hComm As Long
Private stDCB As DCB
Private timeOut As COMMTIMEOUTS
'(1)ポートのハンドル
'(2)DCB構造体を変数に割り付ける
'(3)COMMTIMEOUTS構造体を変数に割り付ける

Private Sub Form_Load()
    Text1.Text = ""
    Text2.Text = ""
    Label1.Caption = "送信文字"
    Label2.Caption = "受信文字"
    Label3.Caption = "簡易通信テストプログラム API"
    Command1.Caption = "通信テスト開始"
End Sub

'(4)Loadイベントプロシージャ
'(5)テキストボックス1の文字設定
'   テキストボックス2の文字設定
'(6)ラベル1の表示文字設定
'   ラベル2の表示文字設定
'   ラベル3の表示文字設定
'(7)コマンドボタンの表示文字設定


Private Sub Command1_Click()

    'シリアルポートをオープンする
    Const GENERIC_READ = &H80000000
    Const GENERIC_WRITE = &H40000000
    Const OPEN_EXISTING = 3
    comname = "COM1"


'(8)Command1のクリックイベントプロシージャ


'(9)読み取り用定数
'(10)書き込み用定数
'(11)既存のファイルの処理
'(12)使用するポートの選択


'(13)ポートのオープン
    hComm = CreateFile(comname, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)

    If hComm = -1 Then
        MsgBox comname & "が使えません", vbCritical
        End
    End If

'(14)ポートのオープン失敗時
'(15)警告メッセージ アイコンを表示
'(16)強制終了


    'シリアル通信の設定
    stDCB.BaudRate = 9600
    stDCB.ByteSize = 8
    stDCB.fBitFields = &H3001

    stDCB.Parity = 0
    stDCB.StopBits = 0
    dummy = SetCommState(hComm, stDCB)


'(17)転送速度の指定
'(18)ビット長の指定
'(19)バイナリモードのフラグを有効にし
'   RTSの制御を設定する(それ以外はFalseにする)
'(20)パリティの設定(パリティなし)
'(21)ストップビット数を指定(1ビット)
'(22)必要な部分だけ書き換える

    'タイムアウトの設定
    timeOut.ReadIntervalTimeout = 500
    timeOut.ReadTotalTimeoutMultiplier = 0
    timeOut.ReadTotalTimeoutConstant = 500
    timeOut.WriteTotalTimeoutMultiplier = 0
    timeOut.WriteTotalTimeoutConstant = 500
    dummy = SetCommTimeouts(hComm, timeOut)


'(23)文字の読み込み待ち時間(500ms)
'    読み込みの1文字あたりの時間
'    読み込みの定数時間(500ms)
'    書き込みの1文字あたりの時間
'    書き込みの定数時間(500ms)
'    タイムアウトの設定

    'データの送信
    Dim wData As String
    Dim wLen As Long
    Dim dLen As Long
    wData = Text1.Text & Chr(13)
    dLen = LenB(StrConv(wData, vbFromUnicode))
    dummy = WriteFile(hComm, ByVal wData, dLen, wLen, 0)


'(24)送信データの変数宣言(文字変数として定義)
'    送信されたデータ長の変数宣言
'    送信するデータ長の変数宣言
'(25)入力データ+リターン符号の付加
'(26)ANSI+DBCS文字でのバイト数に換算
'(27)データの送信(2番目のパラメータにByvalをつける)

    'データの受信
    Dim rData As String
    Dim rLen As Long
    rData = Space(100)
    dummy = ReadFile(hComm, ByVal rData, 100, rLen, 0)
    Text2.Text = RTrim(rData)


    dummy = CloseHandle(hComm)
End Sub


'(28)受信データの変数宣言(文字変数として定義)
'   受信されたデータ長の変数宣言
'(29)100文字分の領域確保
'(30)データの受信(2番目のパラメータにByvalをつける)
'(31)後ろの空白を削除する

'(32)シルアルポートを閉じる


Private Sub Form_Unload(Cancel As Integer)
    dummy = CloseHandle(hComm)
End Sub

'(33)Unoadイベントプロシージャ
'(34)念のためシルアルポートを閉じる


→ここをクリックして、下記のプログラムをダウンロードするようにしてください。<Up Dated>(2001.2.13)
  <ダウンロードする>ファイル名:「txrx1.lzh」 サイズ8.78kバイト

実行ファイル単体で動作します。ソフトはLHA形式で圧縮してあるので、解凍して使ってください。解凍することで現れるフォルダの中にあるEXEファイルを実行すれば起動します。特にインストーラーが付属しているわけではありませんので、プログラムファイルへの登録やショートカットの作成はご自分でなさってください。ソフトを削除したい場合は、そのまま削除してください。このソフトを使用していかなる損害が発生しても、当方は一切責任をとりません。


【プログラムの説明】ここがポイント
このプログラムについて、順を追って解説を加えておきましょう。


(1)ポートのハンドル変数宣言
シリアルポートをCreateFile関数を使ってオープンしたとき、その戻り値がポートのハンドルになります。このハンドル値は、データの送受信時やポートをクローズするときに必要になります。フォームモジュール内の宣言領域(GeneralのDeclarations)に記述します。

(2)DCB構造体の変数割り付け
シリアルポートの設定関数であるSetCommState関数の2番目のパラメータに、DCB構造体が使われていますので、変数を割り付けておきます。フォームモジュール内の宣言領域(GeneralのDeclarations)に記述します。

(3)COMMTIMEOUTS構造体の変数割り付け
タイムアウトの設定関数であるSetCommTimeouts関数の2番目のパラメータに、COMMTIMEOUTS構造体が使われていますので、変数を割り付けておきます。フォームモジュール内の宣言領域(GeneralのDeclarations)に記述します。

(4)Loadイベントプロシージャ
Load イベント プロシージャには、フォームの初期設定を行うコードを記述します。たとえば、各コントロールの既定値を設定したり、リスト ボックス (ListBox) コントロールに表示される内容を記述したり、フォーム レベルの変数を初期化することができます。

(5)テキストボックスの文字設定
テキストボックスの表示文字の初期設定では、表示なしに設定

(6)ラベルの表示文字設定
ラベルの表示文字の設定として、「送信文字」、「受信文字」、「簡易通信プログラム」といった文字を表示

(7)コマンドボタンの表示文字設定
コマンドボタンの表示文字の設定として、「通信テスト開始」といった文字を表示

(8)Command1のクリックイベントプロシージャ
マウスで「Command1」のオブジェクトをポイントした後、マウスボタンを押して離したときに発生します。

(9)読み取り用定数
GENERIC_READ = &H80000000 として読み取り用の定数が定義されています。APIビューアの「定数」の項目にもありますので、そこからコピーしても構いません。

(10)書き込み用定数
GENERIC_WRITE = &H40000000 として書き込み用の定数が定義されています。APIビューアの「定数」の項目にもありますので、そこからコピーしても構いません。

(11)既存のファイルの処理
OPEN_EXISTING = 3 として既存のファイルをオープンする定数が定義されています。APIビューアの「定数」の項目にもありますので、そこからコピーしても構いません。

(12)使用するポートの選択
使用するポートに応じて"COM2"などに変更する。

(13)ポートのオープン
CreateFile関数の詳細は、前ページにあるAPI関数の解説をご覧ください。

(14)ポートのオープン失敗時
CreateFile関数の戻り値は、成功すればハンドル値を返しますが、失敗すると「−1」を返します。

(15)警告メッセージ アイコンを表示
MsgBoxは、ダイアログボックス内にメッセージとして表示する文字列を指定し、vbCritical は警告メッセージ アイコンとして表示します。

(16)強制終了
プログラムの実行を終了させます。

(17)転送速度の指定
DCB構造体についての詳細は、前ページにある解説をご覧ください。
シリアル通信の転送速度を、9600bpsに設定

(18)ビット長の指定
DCB構造体についての詳細は、前ページにある解説をご覧ください。
8ビット長に設定

(19)バイナリモードのフラグを有効にし
   RTSの制御を設定する(それ以外はFalseにする)

fBitFieldsについての詳細は、前ページにある解説をご覧ください。
フラグの部分は、バイナリモードを有効、RTS/CTSの制御だけを指定しました。
ビットのフィールドは、LSBから1ビット目と、13,14ビット目を「1」にします。
すなわち、&H3001です。

(20)パリティの設定
DCB構造体についての詳細は、前ページにある解説をご覧ください。
パリティなし

(21)ストップビット数を指定
DCB構造体についての詳細は、前ページにある解説をご覧ください。
ストップビット数は、1ビット

(22)必要な部分だけ書き換える
(17)〜(21)までの各設定を SetCommState関数で書き換えます。

(23)タイムアウトの設定
COMMTIMEOUTS構造体についての詳細は、前ページにある解説をご覧ください。
100行以下のやりとりなので、字数に関係なく、受信待ち時間、受信時間、送信時間ともタイムアウトの設定を、500msにしました。

(24)送信データに関する変数宣言
送信データの変数宣言(文字変数として定義)、送信されたデータ長の変数宣言、送信するデータ長の変数宣言をします。

(25)入力データ+リターン符号の付加
テキストボックス「Text1」に送信文字が入力されます。入力データの最後にリターンコードを付加しておきます。

(26)ANSI+DBCS文字でのバイト数に換算
英文字は、1文字が1バイトで表現されるANSI文字セットであり、漢字などの文字は1文字が2バイトで表現されるDBCS文字セットを使用しています。したがって、漢字などの2バイト系の文字が混在した場合には、Visual BasicのStrConv関数と、LenB関数を使って、ANSI文字に直した場合のバイト数を求めます。StrConv 関数のにあるvbFromUnicode は文字列を Unicode からシステムの既定のコードに変換します。LenB 関数は、指定した文字列のバイト数を返します。

(27)データの送信
データを送信します。2番目のパラメータは、送信するデータであり文字変数を使う場合には、必ず「ByVal」をつけてください。怠ると保護違反になります。宣言文には、「ByVal」がついていないので実行文の方につけておきます。3番目のパラメータでは、送信したいバイト数を厳密に指定してください。4番目のパラメータは、実際にやりとりしたバイト数が格納されます。5番目のパラメータでは ByVal 0& を与えます(単なる0でもよい)。

(28)受信データに関する変数宣言
受信データの変数宣言、受信されたデータ長の変数宣言をしておきます。

(29)100文字分の領域確保
受信データ文字数として、余裕をみて100文字分の領域を確保しておきます。

(30)データの受信
データを受信します。2番目のパラメータは、受信するデータであり文字変数を使う場合には、必ず「ByVal」をつけてください。怠ると保護違反になります。宣言文には、「ByVal」がついていないので実行文の方につけておきます。3番目のパラメータでは、受信したいバイト数を「100バイト」などのように大きめに指定しておきます。4番目のパラメータで、実際にやりとりしたバイト数がわかりますので、後から必要な文だけ取り出します。5番目のパラメータでは ByVal 0& を与えます(単なる0でもよい)。

(31)後ろの空白を削除する
受信データ文字数として、余裕をみて100文字分の領域(空白)が確保されていますので、削除します。RTrimは、指定した文字列から末尾のスペースを削除します。

(32)シルアルポートを閉じる
CloseHandle関数で、ポートを閉じます。

(33)Unoadイベントプロシージャ
フォームが画面から消去 (アンロード) されるときに発生します。

(34)念のためシルアルポートを閉じる
ポートを確実に閉じるようにCloseHandle関数を付けておきます。


<項目>プログラムの動作確認
PIC側のプログラムは、PIC送受信テスト用のファイル「rxtx.hex」を書き込んでおきます。
あらかじめ、PIC側のシリアル通信動作に問題のないことを、Acknowrichを使って確認しておきます。図6は、今回作成したプログラムの動作画面を示します。

作成プログラムの動作画面
図5.作成プログラムの動作画面

送信文字のテキスト入力欄に適当な文字(漢字などの2バイト文字でも可)を入力し、通信テスト開始のコマンドボタンをクリックしてみてください。PIC側で入力した文字列の最後に「終了」のコメントを付加して送り返してきましたら成功です!

(注)送信文字と付加された終了との文字間に「・」が見られますが、これは入力データの送信時に付加した リターンコードを示しています。



<戻る> <次ページへ>
<TOPページへ>





PC用眼鏡【管理人も使ってますがマジで疲れません】 解約手数料0円【あしたでんき】 Yahoo 楽天 NTT-X Store

無料ホームページ 無料のクレジットカード 海外格安航空券 ふるさと納税 海外旅行保険が無料! 海外ホテル